package uml.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import javax.swing.BorderFactory;
import javax.swing.KeyStroke;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;

import uml.objects.ArrowEnd;

/**
 * Provides access to a set of constants to be used throughout the project.
 * 
 * @author Neil Obetz
 * 
 */

public final class UMLConstants
{
	// Default Sizes
	public static final Dimension PACKAGE_SIZE = new Dimension (400, 400);
	public static final Dimension CLASS_SIZE = new Dimension (200, 100);
	public static final Dimension INTERFACE_SIZE = new Dimension (200, 100);

	// Default colors
	public static final Color PACKAGE_COLOR = new Color (255, 255, 0, 90);
	public static final Color CLASS_COLOR = Color.blue;
	public static final Color INTERFACE_COLOR = Color.RED;
	public static final Color TEXTAREA_COLOR = new Color (0, 0, 0, 0);

	public static final Color BACKGROUND = Color.blue;
	public static final Color COMPONENT_BACKGROUND = Color.white;
	public static final Color INTERFACE_BACKGROUND = new Color (0, 0, 0, 0);
	public static final Color CLASS_BACKGROUND = new Color (255, 255, 255, 0);
	public static final Color NOTE_BACKGROUND = new Color (0, 0, 0, 0);
	public static final Color WINDOW_BACKGROUND = Color.white;
	public static final Color TABBED_PANE_BACKGROUND = Color.white;
	public static final Color DIAGRAM_PANEL_BACKGROUND = Color.white;
	public static final Color ABSTRACT_BACKGROUND = CLASS_BACKGROUND;
	public static final Color SIMPLE_BACKGROUND = CLASS_BACKGROUND;
	public static final Color SIMPLE_ABSTRACT_BACKGROUND = CLASS_BACKGROUND;
	public static final Color ANCHOR_POINT_BACKGROUND_COLOR = new Color (0, 0, 0, 0);

	public static final Color SELECTED_OBJECT_BORDER_COLOR = Color.blue;
	public static final Color CLASS_BORDER_COLOR = new Color(0,0,0,0);
	public static final Color OUTSIDE_BORDER = Color.black;
	public static final Color INSIDE_BORDER = Color.blue;
	public static final Color COMPONENT_INSIDE_BORDER = Color.blue;
	public static final Color COMPONENT_OUTSIDE_BORDER = Color.blue;
	public static final Color ANCHOR_POINT_BORDER_COLOR = Color.blue;
	public static final Color ARROW_END_BORDER_COLOR = Color.black;
	public static final Color ARROW_END_BLACK = Color.black;
	public static final Color ARROW_END_WHITE = Color.WHITE;

	//Default borders
	public static final Border CLASS_BORDER = BorderFactory.createBevelBorder (BevelBorder.RAISED, CLASS_BORDER_COLOR, CLASS_BORDER_COLOR);
	public static final Border CLASS_SELECTED_BORDER = BorderFactory.createBevelBorder(BevelBorder.RAISED, SELECTED_OBJECT_BORDER_COLOR, SELECTED_OBJECT_BORDER_COLOR);
	public static final Border CLASS_FIELD_BORDER = BorderFactory.createLineBorder (CLASS_COLOR, 1);
	public static final Border INTERFACE_BORDER = BorderFactory.createLineBorder (INTERFACE_COLOR, 2);
	public static final Border ABSTRACT_BORDER = CLASS_BORDER;
	public static final Border SIMPLE_BORDER = CLASS_BORDER;
	public static final Border SIMPLE_ABSTRACT_BORDER = CLASS_BORDER;

	public static final Border NORMAL = BorderFactory.createBevelBorder (BevelBorder.RAISED, BACKGROUND,
			OUTSIDE_BORDER, INSIDE_BORDER, OUTSIDE_BORDER);
	public static final Border ACTIVE = BorderFactory.createLineBorder (OUTSIDE_BORDER, 3);
	public static final Border COMPONENT_BORDER = BorderFactory.createLineBorder (COMPONENT_OUTSIDE_BORDER);
	public static final Border HOVER = BorderFactory.createBevelBorder (BevelBorder.RAISED, BACKGROUND, OUTSIDE_BORDER,
			INSIDE_BORDER, OUTSIDE_BORDER);
	public static final Border SELECTED_ANCHOR_POINT_BORDER = BorderFactory.createBevelBorder (BevelBorder.RAISED,
			ANCHOR_POINT_BORDER_COLOR, ANCHOR_POINT_BORDER_COLOR);
	public static final Border UNSELECTED_ANCHOR_POINT_BORDER = null;

	// Font constants
	public static final float DEFAULT_FONT_SIZE = 12;
	public static final Dimension NOTE_SIZE = new Dimension (100, 100);
	public static final Border NOTE_BORDER = null;//BorderFactory.createLineBorder (Color.BLACK);
	public static final Border PACKAGE_BORDER = NOTE_BORDER;
	public static final Dimension MIN_COMPONENTLAYOUT_SIZE = new Dimension (20, 20);

	//Default text
	public static final String[] CLASS_DEFAULT_TEXT = { "Edit name", "Edit attributes", "Edit operations",
			"Edit responsibilities" };
	public static final String[] INTERFACE_DEFAULT_TEXT = { "Edit name", "Edit operations" };
	public static final String[] ABSTRACT_DEFAULT_TEXT = INTERFACE_DEFAULT_TEXT;
	public static final String[] SIMPLE_DEFAULT_TEXT = { "Edit name" };
	public static final String[] NOTE_DEFAULT_TEXT = { "Edit comment" };
	public static final String[] PACKAGE_DEFAULT_TEXT = { "Edit name" };
	public static final String[] SIMPLE_ABSTRACT_DEFAULT_TEXT = ABSTRACT_DEFAULT_TEXT;

	//Default layout parameters for mig layout
	public static final String[] CLASS_LAYOUT_PARAMS = { "wrap 1, fillx", "1[align center]1", "0.5[]0.5" };
	public static final String[] SIMLE_LAYOUT_PARMS = { "fillx", "1[align center]1" };
	public static final String[] INTERFACE_LAYOUT_PARAMS = { "wrap 1, fillx", "1[align center]1", "0.5[]0.5" };
	public static final String[] NOTE_LAYOUT_PARAMS = { "wrap 1, fillx", "[align center]", "" };
	public static final String[] PACKAGE_LAYOUT_PARAMS = { "", "[align center]", "" };
	public static final String[] ABSTRACT_LAYOUT_PARAMS = CLASS_LAYOUT_PARAMS;
	public static final String[] SIMPLE_LAYOUT_PARAMS = CLASS_LAYOUT_PARAMS;
	public static final String[] SIMPLE_ABSTRACT_LAYOUT_PARAMS = CLASS_LAYOUT_PARAMS;
	
	
	//Object Layers
	public static final Integer CLASS_LAYER = 50;
	public static final Integer INTERFACE_LAYER = 50;
	public static final Integer PACKAGE_LAYER = 40;
	public static final Integer NOTE_LAYER = 60;
	public static final Integer ARROW_LAYER = 70;
	public static final Integer ANCHOR_POINT_LAYER = 70;
	public static final Integer SIMPLE_LAYER = 50;
	public static final Integer SIMPLE_ABSTRACT_LAYER = 50;
	public static final Integer ABSTRACT_LAYER = 50;
	//Arrow Constants
	/*
	 * Strokes use an array of floats to represent the spacing inbetween the dashes.
	 * Each element in the array represents a length of the stroke.
	 * Even indexes are visible odd are invisible.
	 */
	public static final float[] DASH = { 20, 10 };
	//represents how thick the line is
	public static final int ARROW_WIDTH = 2;
	public static final BasicStroke REGULAR_LINE = new BasicStroke (ARROW_WIDTH, BasicStroke.CAP_ROUND,
			BasicStroke.JOIN_MITER);
	public static final BasicStroke DASHED_LINE = new BasicStroke (ARROW_WIDTH, BasicStroke.CAP_ROUND,
			BasicStroke.JOIN_MITER, 1, DASH, 0);
	public static final ArrowEnd BLACK_ARROW_HEAD = new ArrowEnd (ARROW_END_BLACK, initHead ());
	public static final ArrowEnd WHITE_ARROW_HEAD = new ArrowEnd (ARROW_END_WHITE, initHead ());
	public static final ArrowEnd BLACK_DIAMOND = new ArrowEnd (ARROW_END_BLACK, initDiamond ());
	public static final ArrowEnd WHITE_DIAMOND = new ArrowEnd (ARROW_END_WHITE, initDiamond ());
	public static final ArrowEnd NO_END = new ArrowEnd (ARROW_END_BLACK, empty ());
	public static final Point ARROW_START_LOCATION = new Point (125, 125);
	public static final Point ARROW_END_LOCATION = new Point (250, 250);

	public static Polygon initDiamond ()
	{
		int x[] = { 0, -15, -30, -15 };
		int y[] = { 0, 10, 0, -10 };
		Polygon diamond = new Polygon (x, y, 4);
		return diamond;
	}

	public static Polygon empty ()
	{
		int x[] = { 0 };
		int y[] = { 0 };
		return new Polygon (x, y, 1);
	}

	public static Polygon initHead ()
	{
		int[] x = { -20, 2, -20 };
		int[] y = { 10, 0, -10 };
		return new Polygon (x, y, 3);
	}

	public static final Dimension POINT_SIZE = new Dimension (20, 20);
	public static final Color ARROW_COLOR = Color.BLACK;
	

	/*
	*Instructions to add key shortcuts
	*the addShortcut method takes in a string and a UMLEventId
	*
	*the string is defined as following:
	*string -> <modifiers>* (<typedID> | <pressedReleasedID>)
	*modifiers -> shift | control | ctrl | meta | alt | altGraph
	*typedID -> typed <typedKey>
	*typedKey -> [:Unicode Character:]
	*pressedReleasedID -> (pressed | released) key
	*key -> [:Keyevent key code:]
	*
	*Some english comments
	*A key is the same as the text in the KeyEvent keycodes after "VK_"
	*The main format you will use is "modifiers* key"
	*/

	//	*/
	//	addShortcut("control Q", UMLEventId.APPLICATION_EXIT);
	//	addShortcut("control N", UMLEventId.CREATE_DIAGRAM);
	//	addShortcut("alt N", UMLEventId.MAKE_NOTE);
	//	addShortcut("alt C", UMLEventId.MAKE_CLASS);
	//	addShortcut("alt P", UMLEventId.MAKE_PACKAGE);
	//	addShortcut("alt I", UMLEventId.MAKE_INTERFACE);
	//	addShortcut("control D", UMLEventId.DELETE);

	//Parses a string and returns a KeyStroke. The string must have the following syntax: 
	//    <modifiers>* (<typedID> | <pressedReleasedID>)
	//
	//    modifiers := shift | control | ctrl | meta | alt | altGraph
	//    typedID := typed <typedKey>
	//    typedKey := string of length 1 giving Unicode character.
	//    pressedReleasedID := (pressed | released) key
	//    key := KeyEvent key code name, i.e. the name following "VK_".
	// If typed, pressed or released is not specified, pressed is assumed. Here are some examples: 
	//     "INSERT" => getKeyStroke(KeyEvent.VK_INSERT, 0);
	//     "control DELETE" => getKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);
	//     "alt shift X" => getKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | 
	//      InputEvent.SHIFT_MASK);
	//     "alt shift released X" => getKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | 
	//      InputEvent.SHIFT_MASK, true);
	//     "typed a" => getKeyStroke('a');
	// In order to maintain backward-compatibility, specifying a null String, or a String which is 
	//  formatted incorrectly, returns null.
	//Parameters:
	//	

	public static KeyStroke EXIT_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_Q, InputEvent.CTRL_MASK);
	public static KeyStroke NEW_DIAGRAM_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_N, InputEvent.CTRL_MASK);
	public static KeyStroke CLOSE_DIAGRAM_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_C, InputEvent.CTRL_MASK);
	public static KeyStroke LOAD_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_O, InputEvent.CTRL_MASK);
	public static KeyStroke SAVE_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_S, InputEvent.CTRL_MASK);
	public static KeyStroke PRINT_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_P, InputEvent.CTRL_MASK);
	public static KeyStroke CANCEL_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_W, InputEvent.CTRL_MASK);
	
	public static KeyStroke NOTE_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_N, InputEvent.ALT_MASK);
	public static KeyStroke ABSTRACT_CLASS_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_A, InputEvent.ALT_MASK);
	public static KeyStroke SIMPLE_CLASS_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_S, InputEvent.ALT_MASK);
	public static KeyStroke CLASS_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_C, InputEvent.ALT_MASK);
	public static KeyStroke PACKAGE_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_P, InputEvent.ALT_MASK);
	public static KeyStroke INTERFACE_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_I, InputEvent.ALT_MASK);
	public static KeyStroke DELETE_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);
	public static KeyStroke GENERALIZATION_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_I, InputEvent.SHIFT_MASK);
	public static KeyStroke ASSOCIATION_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_J, InputEvent.SHIFT_MASK);
	public static KeyStroke COMPOSITION_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_K, InputEvent.SHIFT_MASK);
	public static KeyStroke AGGREGATION_STROKE = KeyStroke.getKeyStroke (KeyEvent.VK_M, InputEvent.SHIFT_MASK);
	

}
